// Copyright 2013 The Chromium Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.

#include "media/capture/video_capture_types.h"

#include "base/logging.h"
#include "base/macros.h"
#include "base/strings/stringprintf.h"
#include "media/base/limits.h"
#include "media/base/video_frame.h"

namespace media {

// This list is ordered by precedence of use.
static VideoPixelFormat const kSupportedCapturePixelFormats[] = {
    PIXEL_FORMAT_I420,
    PIXEL_FORMAT_YV12,
    PIXEL_FORMAT_NV12,
    PIXEL_FORMAT_NV21,
    PIXEL_FORMAT_UYVY,
    PIXEL_FORMAT_YUY2,
    PIXEL_FORMAT_RGB24,
    PIXEL_FORMAT_RGB32,
    PIXEL_FORMAT_ARGB,
    PIXEL_FORMAT_MJPEG,
};

VideoCaptureFormat::VideoCaptureFormat()
    : frame_rate(0.0f)
    , pixel_format(PIXEL_FORMAT_UNKNOWN)
    , pixel_storage(PIXEL_STORAGE_CPU)
{
}

VideoCaptureFormat::VideoCaptureFormat(const gfx::Size& frame_size,
    float frame_rate,
    VideoPixelFormat pixel_format)
    : frame_size(frame_size)
    , frame_rate(frame_rate)
    , pixel_format(pixel_format)
    , pixel_storage(PIXEL_STORAGE_CPU)
{
}

VideoCaptureFormat::VideoCaptureFormat(const gfx::Size& frame_size,
    float frame_rate,
    VideoPixelFormat pixel_format,
    VideoPixelStorage pixel_storage)
    : frame_size(frame_size)
    , frame_rate(frame_rate)
    , pixel_format(pixel_format)
    , pixel_storage(pixel_storage)
{
}

bool VideoCaptureFormat::IsValid() const
{
    return (frame_size.width() < media::limits::kMaxDimension) && (frame_size.height() < media::limits::kMaxDimension) && (frame_size.GetArea() >= 0) && (frame_size.GetArea() < media::limits::kMaxCanvas) && (frame_rate >= 0.0f) && (frame_rate < media::limits::kMaxFramesPerSecond) && (pixel_format >= PIXEL_FORMAT_UNKNOWN && pixel_format <= PIXEL_FORMAT_MAX);
}

size_t VideoCaptureFormat::ImageAllocationSize() const
{
    return VideoFrame::AllocationSize(pixel_format, frame_size);
}

// static
std::string VideoCaptureFormat::ToString(const VideoCaptureFormat& format)
{
    // Beware: This string is parsed by manager.js:parseVideoCaptureFormat_,
    // take care when changing the formatting.
    return base::StringPrintf(
        "(%s)@%.3ffps, pixel format: %s, storage: %s",
        format.frame_size.ToString().c_str(), format.frame_rate,
        VideoPixelFormatToString(format.pixel_format).c_str(),
        PixelStorageToString(format.pixel_storage).c_str());
}

// static
std::string VideoCaptureFormat::PixelStorageToString(
    VideoPixelStorage storage)
{
    switch (storage) {
    case PIXEL_STORAGE_CPU:
        return "CPU";
    }
    NOTREACHED() << "Invalid VideoPixelStorage provided: "
                 << static_cast<int>(storage);
    return std::string();
}

// static
bool VideoCaptureFormat::ComparePixelFormatPreference(
    const VideoPixelFormat& lhs,
    const VideoPixelFormat& rhs)
{
    auto* format_lhs = std::find(
        kSupportedCapturePixelFormats,
        kSupportedCapturePixelFormats + arraysize(kSupportedCapturePixelFormats),
        lhs);
    auto* format_rhs = std::find(
        kSupportedCapturePixelFormats,
        kSupportedCapturePixelFormats + arraysize(kSupportedCapturePixelFormats),
        rhs);
    return format_lhs < format_rhs;
}

VideoCaptureParams::VideoCaptureParams()
    : resolution_change_policy(RESOLUTION_POLICY_FIXED_RESOLUTION)
    , power_line_frequency(PowerLineFrequency::FREQUENCY_DEFAULT)
{
}

bool VideoCaptureParams::IsValid() const
{
    return requested_format.IsValid() && resolution_change_policy >= RESOLUTION_POLICY_FIXED_RESOLUTION && resolution_change_policy <= RESOLUTION_POLICY_LAST && power_line_frequency >= PowerLineFrequency::FREQUENCY_DEFAULT && power_line_frequency <= PowerLineFrequency::FREQUENCY_MAX;
}

} // namespace media
